import ProtoDispatcher from "../../common/core/ProtoDispatcher";
import { Protocol, ProtoVo } from "../../common/protocol/Protocol";
import App from "../App";

export enum ConnectionEvent {
    joinOk,
    joinErr,
}

/** 连接 */
export default class Conn {

    /** 当前连接 */
    ws = null;
    /** 服务器地址 */
    url = 'ws://192.168.8.194:8848'
    // url = 'ws://192.168.2.151:8848'
    private _pd: ProtoDispatcher = new ProtoDispatcher()
    get pd() { return this._pd }
    /** 回调 */
    callbacks: Map<ConnectionEvent, Function[]> = new Map()

    /** 初始化 */
    constructor() {

    }

    /** 初始化 */
    start(name: string) {
        //创建连接
        let ws = new WebSocket(this.url)
        ws.binaryType = "arraybuffer"

        ws.onopen = e => {
            console.log(e);

            this.onConnect()


            //加入失败
            this._pd.on(Protocol.S2C_JOIN_ERR, this, data => {
                this.onJoinErr(data.msg)
            })
            //加入成功
            this._pd.on(Protocol.S2C_JOIN_OK, this, data => {
                this.onJoinOk(data)
            })

            ws.onmessage = e => {
                this._pd.onMsg(new Uint8Array(e.data))
            }

            //断开连接
            ws.onclose = (e) => {
                this.onDisconnect()
            }

            ws.send(this._pd.from(Protocol.C2S_JOIN, { name }))

        }

        this.ws = ws
    }

    /** 发送协议 */
    send<Protocol extends keyof ProtoVo.Def>(protocol: Protocol, data?: ProtoVo.Def[Protocol]) {
        this.ws.send(this._pd.from(protocol, data))
    }

    /** 当连接成功时 */
    onConnect() {
        console.log('已连接到服务器');
    }

    /** 当加入失败 */
    onJoinErr(msg) {
        console.log("加入失败:" + msg);
        (this.callbacks.get(ConnectionEvent.joinErr) || []).forEach(cb => cb(msg))
    }

    onJoinOk(data: ProtoVo.IS2C_JOIN_OK) {
        /** 当加入游戏 */
        console.log("加入游戏");
        //绑定数据
        App.startRemote(data.id, this);
        // //事件回调
        (this.callbacks.get(ConnectionEvent.joinOk) || []).forEach(cb => cb())
    }

    /** 当断开连接 */
    onDisconnect() {
        console.log('断开连接');
        this.ws = null
    }

    /** 绑定事件回调 */
    on(event: ConnectionEvent, callback: Function) {
        let cbs = (this.callbacks.get(event) || [])
        cbs.push(callback)
        this.callbacks.set(event, cbs)
    }
}